package com.chenyuxin.ilp.service.file.Impl;

import com.chenyuxin.ilp.exception.BaseException;
import com.chenyuxin.ilp.model.enums.exception.ExceptionEnums;
import com.j256.simplemagic.ContentInfo;
import com.j256.simplemagic.ContentInfoUtil;
import io.minio.*;
import io.minio.http.Method;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;


@Service
@Slf4j
public class MinioServiceImpl {
    @Autowired
    private MinioClient minioClient;
    // 上传文件
    public Boolean upload(String localFilePath,String bucket,String objectName,String extension){
        ContentInfo extensionMatch = ContentInfoUtil.findExtensionMatch(extension);
        String mimeType = MediaType.APPLICATION_OCTET_STREAM_VALUE;
        if(extensionMatch!=null){
            mimeType = extensionMatch.getMimeType();
        }
        try{
            UploadObjectArgs testBucket = UploadObjectArgs.builder()
                    .bucket(bucket)
                    .object(objectName)
                    .filename(localFilePath)
                    .contentType(mimeType)
                    .build();
            minioClient.uploadObject(testBucket);
            System.out.println("上传成功");
            return true;
        }catch (Exception exception){
            exception.printStackTrace();
            System.out.println("上传失败！");
        }
        return false;
    }
    // 删除文件
    public Boolean delete(String bucket,String objectName){
        RemoveObjectArgs testBucket = RemoveObjectArgs.builder()
                .bucket(bucket).object(objectName).build();
        try {
            minioClient.removeObject(testBucket);
        } catch (Exception e) {
            e.printStackTrace();
            throw new BaseException(ExceptionEnums.SYSTEM_ERROR);
        }
        return true;
    }
    // 修改文件路径
    public void changeFilePath(String bucket,String oldObjectName,String newObjectName){
        String downloadFilePath = "";
        // 下载minio文件
        try {
            String fileName = newObjectName.substring(newObjectName.lastIndexOf('/') + 1);
            // 下载文件到本地指定路径
            downloadFilePath = "/Users/chenyuxin/比赛/2025服外软件设计校赛/Service-Outsourcing-Competition-Project/rear/intelligent-learning-platform/src/main/resources/tempfile/"+fileName;  // 本地文件保存路径
            GetObjectArgs getObjectArgs = GetObjectArgs.builder()
                    .bucket(bucket)
                    .object(oldObjectName)
                    .build();
            InputStream inputStream = minioClient.getObject(getObjectArgs);
            try (FileOutputStream outputStream = new FileOutputStream(downloadFilePath)) {
                byte[] buffer = new byte[1024];
                int bytesRead;
                while ((bytesRead = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, bytesRead);
                }
            }
        } catch (Exception e) {
            log.error("下载minio文件出错:{}",e.getMessage());
            throw new BaseException(ExceptionEnums.SYSTEM_ERROR);
        }
        // 上传文件到新路径
        String extension = newObjectName.substring(newObjectName.lastIndexOf('.') + 1);
        ContentInfo extensionMatch = ContentInfoUtil.findExtensionMatch(extension);
        String mimeType = MediaType.APPLICATION_OCTET_STREAM_VALUE;
        if(extensionMatch!=null){
            mimeType = extensionMatch.getMimeType();
        }
        try {
            UploadObjectArgs testBucket = UploadObjectArgs.builder()
                    .bucket(bucket)
                    .object(newObjectName)
                    .filename(downloadFilePath)
                    .contentType(mimeType)
                    .build();
            minioClient.uploadObject(testBucket);
        } catch (Exception e) {
            log.error("上传文件到minio文件出错:{}",e.getMessage());
            throw new BaseException(ExceptionEnums.SYSTEM_ERROR);
        }
        // 删除本地文件
        File localFile = new File(downloadFilePath);
        if (localFile.exists() && localFile.isFile()) {
            boolean deleted = localFile.delete();
            if (!deleted) {
                log.error("删除本地文件失败:"+downloadFilePath);
            }
        } else {
            log.error("文件不存在:"+downloadFilePath);
        }


        // 删除旧文件
        try {
            minioClient.removeObject(RemoveObjectArgs.builder()
                    .bucket(bucket)
                    .object(oldObjectName)
                    .build()
            );
        } catch (Exception e) {
            log.error("删除minio旧文件失败:{}",e.getMessage());

            // **回滚操作**：删除刚上传的新文件，确保 MinIO 状态一致
            try {
                minioClient.removeObject(RemoveObjectArgs.builder()
                        .bucket(bucket)
                        .object(newObjectName)
                        .build()
                );
                log.info("已回滚上传的新文件 {}", newObjectName);
            } catch (Exception rollbackEx) {
                log.error("回滚失败，新文件 {} 可能残留，请手动删除", newObjectName);
            }
            throw new BaseException(ExceptionEnums.SYSTEM_ERROR);
        }
    }
    // 获取文件预览url
    public String getPreviewUrl(String bucket,String objectFileName){
        String previewUrl = null;
        try {
            previewUrl = minioClient.getPresignedObjectUrl(
                    GetPresignedObjectUrlArgs.builder()
                            .method(Method.GET)
                            .bucket(bucket)
                            .object(objectFileName)
                            .expiry(2, TimeUnit.HOURS)  // 过期时间 2 小时
                            .build()
            );
        } catch (Exception e){
            log.error("获取用户预览url失败,objectFileName:{}",objectFileName);
            throw new BaseException(ExceptionEnums.SYSTEM_ERROR);
        }
        return previewUrl;
    }
    // 下载文件二进制信息
    public byte[] download(String objectName){
        byte[] content = null;
        try {
            // 获取文件流
            InputStream stream = minioClient.getObject(
                    GetObjectArgs.builder()
                            .bucket("files")
                            .object(objectName)
                            .build()
            );
            // 读取文件内容
            content = stream.readAllBytes();
            stream.close();
        }catch (Exception e){
            log.error("下载minio文件失败,objectName:{},errorMessage:{}",objectName,e.getMessage());
            throw new BaseException(ExceptionEnums.SYSTEM_ERROR);
        }
        return content;
    }

}
